package base.thread_demo.demo06;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 单生产者（交替生产）单消费者交替生产消费程序设计。
 * 一个生产者负责生产（交替生产包子、馒头），一个消费者负责消费。符合生产一个，立马消费一个顺序
 *
 * 该案例在多生产者消费者下也是线程安全的：因为Input.i这个交替“包子/馒头”判断逻辑包含在了同步代码块内部。
 */
public class ResourceDemo {
    public static void main(String[] args) {
        Resource r = new Resource(false);
        Input in = new Input();
        Output out = new Output();

        new Thread(()->{
            try {
                in.print(r);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t1").start();
        new Thread(()->{
            try {
                in.print(r);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t3").start();

        new Thread(()->{
            try {
                out.print(r);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t2").start();
        new Thread(()->{
            try {
                out.print(r);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t4").start();

    }
}

class Input {
    private static final Logger log = LoggerFactory.getLogger(Input.class);
    private int i=0;
    public Input(){}

    public void print(Resource r) throws InterruptedException {
        while (true){
            synchronized (r) {
                if (!r.isFlag()) {
                    if (i == 0) {
                        r.setName("包子");
                    } else {
                        r.setName("馒头");
                    }
                    r.setFlag(true);
                    i = (i + 1) % 2;
                    log.info("------------> {} 生产了 {}", Thread.currentThread().getName(), r.getName());
                    try {
                        Thread.sleep(20);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }else{
                    r.notifyAll();
                    r.wait();
                }
            }
        }
    }
}

class Output {
    private static final Logger log = LoggerFactory.getLogger(Output.class);
    public Output(){}

    public void print(Resource r) throws InterruptedException {
        while (true){
            synchronized (r) {
                if (r.isFlag()) {
                    log.info("{} 消费了 {}", Thread.currentThread().getName(), r.getName());
                    r.setName("");
                    r.setFlag(false);
                    try {
                        Thread.sleep(30);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }else{
                    r.notifyAll();
                    r.wait();
                }
            }
        }
    }
}

class Resource {
    private String name;
    private boolean flag;

    public Resource(boolean flag){
        this.flag = flag;
    }

    @Override
    public String toString() {
        return "Resource{" +
                "name='" + name + '\'' +
                ", flag=" + flag +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }
}

